//@author A0078695H
/*
Parser

To take command input and perform actions accordingly.
To take command input(partial or full) and provide feedback/auto complete.
*/

#ifndef _PARSER_h_
#define _PARSER_h_

#include <iostream>
#include <cstring>
#include <numeric>

#include "main.h"
#include "task.h"
#include "records.h"
#include "command.h"
#include "CmdAdd.h"
#include "CmdDisplay.h"
#include "CmdClear.h"
#include "CmdDel.h"
#include "CmdSort.h"
#include "CmdFilter.h"
#include "CmdSearch.h"
#include "CmdExit.h"
#include "CmdInvalid.h"
#include "CmdUpdate.h"
#include "CmdDone.h"
#include "CmdHelp.h"
#include "cmdUndo.h"
#include "cmdRedo.h"
#ifndef Q_MOC_RUN
#include "boost/algorithm/string.hpp"
#include "boost/algorithm/string/trim_all.hpp"
#endif

using namespace std;

class Parser {
private:
	//Attributes
	Records* displayRecords;
	Records* taskList;
public:
	//Methods/Commands
	Cmd * createAdd(vector<string> params, string orig);
	Cmd * createDisplay(vector<string> params, string orig);
	Cmd * createDel(vector<string> params, string orig);
	vector<int> parseDeleteRange(string argStr);
	Cmd * createClear(vector<string> params, string orig);
	Cmd * createExit(vector<string> params, string orig);
	Cmd * createSort(vector<string> params, string orig);
	Cmd * createFilter(vector<string> params, string orig);
	Cmd * createSearch(vector<string> params, string orig);
	Cmd * createInvalid(vector<string> params, string orig, ErrorType errType);
	Cmd * createUpdate(vector<string> params, string orig);
	Cmd * createDone(vector<string> params, string orig);
	Cmd * createHelp(vector<string> params, string orig, string cmdTypeString);
	Cmd * createRedo(vector<string> params, string orig);
	Cmd * createUndo(vector<string> params, string orig);
	// constants
	const static string COMMAND_ADD;
	const static string COMMAND_DISPLAY;
	const static string COMMAND_DELETE;
	const static string COMMAND_CLEAR;
	const static string COMMAND_SORT;
	const static string COMMAND_SEARCH;
	const static string COMMAND_FILTER;
	const static string COMMAND_EXIT;
	const static string COMMAND_INVALID;
	const static string COMMAND_UPDATE;
	const static string COMMAND_DONE;
	const static string COMMAND_UNDONE;
	const static string COMMAND_HELP;
	const static string COMMAND_REDO;
	const static string COMMAND_UNDO;

	//To store corresponding commands.
	vector<Cmd*> commandList;
	vector<Cmd*> getCommandList();


	// the old setRecords for cParser. 
	void setDisplayRecords(Records* r);
	
	// initialize replaced by setTaskListRecords
	//int initialize(Records* rec);
	void setTaskListRecords(Records* r);

	void splitStringWithDelim(const std::string &s, char delim, std::vector<std::string> &elems);
	void splitCmdStringWithFirstDelim(const std::string &s, char delim, std::vector<std::string> &elems);
	//Parse for command
	auto_ptr<Cmd> parse(string commandStr);

	//@author A0096566M
	vector<string> getFeedback(string userinput);

	//Misc functions from fParser
	static vector<string> tokenize(string s, string delim);
	static string concatenate(vector<string> str);
	static int isBasicCommand(string s);
	static vector<string> filterBeginsWith(vector<string> s, string toMatch);
	static int findDates(vector<string> s, vector<Date>* datesFound, vector<string>* notDates);
	static int findTags(vector<string> searchString, vector<string>* tags, vector<string>* notTags);
	static Task stringToTask(string s);
	static unsigned int editDistance(const string &s1, const string & s2);

};

#endif